using GZ.Common.Data;
using Newtonsoft.Json;
using GZ.DB.Repository.wcs_yb;
using GZ.DB.Entity.wcs_yb;
using GZ.DB.IRepository.wcs_yb;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Configuration;
using GZ.Projects.WCS_SVC;
using System.Net.NetworkInformation;
using GZ.Common.Code;

namespace GZ.Projects.WCS_SVC
{

	#region IC01.作业任务创建M

	/// <summary>
	/// wms任务下发接口参数
	/// </summary>
	[Serializable]
	
	public class ToWmsCreateOrderRequest
	{
		public string taskNo;
		public string groupNo;
		public string taskType;
		public int priority;
		public string from;
		public string to;
		public string cntrNo;
		public string roadWay; //新增特殊流程使用，巷道号
		public string cntrType;  //托盘类型
		public object extData;
	}

	#endregion

	#region IC02.作业任务取消C
	/// <summary>
	/// wms取消任务接口参数
	/// </summary>
	[Serializable]
	public class ToWmsCancelOrderRequest
	{
		public string taskNo;
	}
	#endregion

	#region IC03.设备状态获取G
	[Serializable]
	public class ToWmsGetStateRequest
	{
		public List<string> deviceNo; //设备号列表
	}

	#endregion


	#region IC04.任务优先级调整

	[Serializable]
	public class ToWmsOrderPriorityRequest
	{
		public string taskNo;
		public int priority;
	}
	#endregion
	#region IC05.是否允许进入

	[Serializable]
	public class ToWmsIsAllowRequest
	{
		public string requestPk;
		public int trkType;
		public string stnNo;
		public string carNo;
		public string clientCode;
	}
	

	#endregion

	#region Response
	/// <summary>
	/// 任务下发、取消任务、获取设备状态、修改优先级返回参数
	/// </summary>
	[Serializable]
	public class DeviceData
	{
		public string deviceNo;
		public int status;   //设备状态或输送线工位状态

	}
	[Serializable]
	public class InOutAllowData
	{
		public int isAllow;   //是否允许进入
		public string msg;
	}
	[Serializable]
	public class Data
	{
		public object[] msg;
	}
	[Serializable]
	public class ToWmsResponseOrderData
	{
		public int code;
		public string msg;
		public List<Data> data;
	}
	[Serializable]
	public class ToWmsResponseStateData
	{
		public int code;
		public string msg;
		public List<DeviceData> data;
	}
	#endregion

	#region wms货位转换
	/// <summary>
	/// 转换为wcs货位,并获取排列层
	/// </summary>
	[Serializable]
	public class WcsLoc
	{
		public string transWcs;
		public int pai;
		public int lie;
		public int ceng;
	}

	#endregion
	[Serializable]
	public class ToWmsReportRequest
	{
		public string taskNo;
		public string subTaskNo;  //wcs的子任务号
		public int status;
		public string deviceNo;  //巷道号
		public string errCode;
		public string loc;
	}

	[Serializable]
	public class ToWmsDestRequest
	{
		public string taskNo;
		public string loc;
		public string applyType;
		public string cntrNo;
	}

	[Serializable]
	public class ToWmsCntrRequest
	{
		public string cntrNo;
	}

	[Serializable]
	public class ToWmsCntrRequestReponse
	{
		public string deviceNo;
		public string errCode;
		public string errMsg;
	}

	public class WCSTOWMS
	{
		private static readonly string UrlNotify = ConfigurationManager.AppSettings["WcsNotifyTask"];
		private static readonly string UrlDest = ConfigurationManager.AppSettings["WcsApplyDest"];
		/// <summary>
		/// 任务状态上报
		/// </summary>
		public bool FeedInfoToWms(ToWmsReportRequest mainMissionRequest, out string responseMsg ,out int statusCode)
		{
			string msg = $"\r\n[wcs反馈任务信息至wms：Start{DateTime.Now:yyyy/MM/dd HH:mm:ss:fff}";
			statusCode = 0;
			responseMsg = null;
			try
			{
				string input = Json.ToJson(mainMissionRequest);
				msg += $"\r\n\t上报WMS状态json:[{input}]{DateTime.Now:yyyy/MM/dd HH:mm:ss:fff}";
				string json = new HttpClient().Call("POST", input, UrlNotify, out string resMsg,out int resCode);
				msg += $"\r\n\t收到WMS回复json:[{json}]{DateTime.Now:yyyy/MM/dd HH:mm:ss:fff}";
				ToWmsResponseOrderData response = Json.ToObject<ToWmsResponseOrderData>(json);
				if (response != null && response.code == 0)
				{
					responseMsg = json;
					statusCode = resCode;
					return true;
				}
				else
				{
					responseMsg = json;
					statusCode = resCode;
					return false;
				}
			}
			catch (Exception ex)
			{
				msg += ex.Message;
				responseMsg = ex.Message;
				return false;
			}
			finally
			{
				msg = msg.Replace('\'', '\"');
				Conn.YBlog.Info(1, $"wcs反馈任务信息至wms ", 1, msg);
			}
		}
		public bool ApplyDestToWms(List<ToWmsDestRequest> destRequest, out string responseMsg,out int statusCode)
		{
			string msg = $"\r\n[wcs申请任务终点至wms：Start{DateTime.Now:yyyy/MM/dd HH:mm:ss:fff}";
			statusCode = 0;
			responseMsg = null;
			try
			{
				string input = Json.ToJson(destRequest);
				msg += $"\r\n\t上报WMS状态json:[{input}]{DateTime.Now:yyyy/MM/dd HH:mm:ss:fff}";
				string json = new HttpClient().Call("POST", input, UrlDest, out string resMsg ,out int resCode);
				msg += $"\r\n\t收到WMS回复json:[{json}]{DateTime.Now:yyyy/MM/dd HH:mm:ss:fff}";
				ToWmsResponseOrderData response = Json.ToObject<ToWmsResponseOrderData>(json);
				if (response != null && response.code == 0)
				{
					responseMsg = json;
					statusCode = resCode;
					return true;
				}
				else
				{
					responseMsg = json;
					statusCode = resCode;
					return false;
				}
			}
			catch (Exception ex)
			{
				msg += ex.Message;
				responseMsg = ex.Message;
				return false;
			}
			finally
			{
				msg = msg.Replace('\'', '\"');
				Conn.YBlog.Info(1, $"wcs反馈任务信息至wms ", 1, msg);
			}
		}
	}
	
	public static class ToWmsHandle
	{
		public static int DeviceTaskIdGen()
		{
			int maxID = 0;
			var taskList = new MainMissionRepository().FindDataTable(
				"SELECT IDENT_CURRENT('pcm_MainMission')",
				new System.Data.Common.DbParameter[0]
			);
			//让设备编号在200000 -299999内循环
			if (taskList != null && taskList.Rows.Count > 0)
			{
				// 转 decimal 再转换为 int
				decimal currentId = Convert.ToDecimal(taskList.Rows[0][0]);
				maxID = ((int)currentId) % 100000; // 保持 5 位循环
			}

			string idStr = maxID.ToString().PadLeft(5, '0');
			return Convert.ToInt32("2" + idStr); // 前缀 2
		}
		/// <summary>
		/// 任务回复 ToWmsResponseOrderData JSON 文本
		/// </summary>
		private static string BuildResponse(int code, string msg, List<Data> data)
		{
			// 截断 msg 到 256 字符,系统异常返回值太长，需要截断
			if (!string.IsNullOrEmpty(msg) && msg.Length > 256)
				msg = msg.Substring(0, 256);
			if (data == null)
			{
				data = new List<Data>();
			}

			var resp = new ToWmsResponseOrderData //任务回复创建、取消
			{
				code = code,
				msg = msg,
				data = data
			};
			return JsonConvert.SerializeObject(resp);
		}

		private static string DvcStateResponse(int code, string msg, List<DeviceData> data)
		{
			// 截断 msg 到 256 字符,系统异常返回值太长，需要截断
			if (!string.IsNullOrEmpty(msg) && msg.Length > 256)
				msg = msg.Substring(0, 256);
			if (data == null)
				data = new List<DeviceData>();
			
			var resp = new ToWmsResponseStateData //状态获取回复
			{
				code = code,
				msg = msg,
				data = data
			};
			return JsonConvert.SerializeObject(resp);
		}
		
		private static string IsAllowResponse(int isAllow, string msg)
		{
			// 截断 msg 到 256 字符,系统异常返回值太长，需要截断
			if (!string.IsNullOrEmpty(msg) && msg.Length > 256)
				msg = msg.Substring(0, 256);
			var resp = new InOutAllowData //允许进入回复
			{
				isAllow = isAllow,
				msg = msg,
			};
			return JsonConvert.SerializeObject(resp);
		}

		/// <summary>
		/// IC01.作业任务创建M
		/// </summary>
		/// <param name="requestJson"></param>
		/// <returns></returns>
		public static string CreateOrder(string requestJson)
		{
			//string respJson = string.Empty;
			try
			{
				var request = JsonConvert.DeserializeObject<ToWmsCreateOrderRequest>(requestJson);
				if (request == null)
				{
					return BuildResponse(-1, "收到的json格式不正确", null);
				}

				// 1. 任务号不能为空
				if (string.IsNullOrEmpty(request.taskNo))
				{
					return BuildResponse(-1, "taskNo不能为空", null);
				}
				// 2. 托盘号不能为空
				if (string.IsNullOrEmpty(request.cntrNo))
				{
					return BuildResponse(-1, "cntrNo不能为空", null);
				}
				// 3. 托盘号不能为空
				if (string.IsNullOrEmpty(request.cntrType))
				{
					return BuildResponse(-1, "cntrNo不能为空", null);
				}
				// 4. 起始库位不能为空
				if (string.IsNullOrEmpty(request.from))
				{
					return BuildResponse(-1, "from不能为空", null);
				}
				// 5. 起始库位不能为空
				if (string.IsNullOrEmpty(request.to))
				{
					return BuildResponse(-1, "to不能为空", null);
				}
				MainMissionEntity mission = new MainMissionEntity();
				mission.order_no = request.taskNo;
				mission.task_no = request.taskNo;
				int deviceTaskId = DeviceTaskIdGen(); // 在循环外获取初始ID值
				mission.device_task_no = deviceTaskId.ToString(); // 为每个任务递增ID
				mission.tray_code = request.cntrNo;
				mission.tray_type = request.cntrType;
				mission.group_no = request.groupNo;
				mission.order_priority = request.priority;
				mission.task_priority = request.priority;
				// 使用StationConvertHelper转换from/to为WCS货位
				// 如果是LXK-、TPK-格式则不转换，其他通过字典转换
				string convertedFrom = StationConvertHelper.ConvertWmsToWcs(request.from);
				string convertedTo = StationConvertHelper.ConvertWmsToWcs(request.to);
				mission.start_position = convertedFrom;
				mission.end_position = string.IsNullOrEmpty(convertedTo) ? "NULL" : convertedTo;

				switch (request.taskType)
				{
					case "1":
						mission.task_type = "ST_In";
						mission.order_type = "R";
						break;
					case "2":
						mission.task_type = "ST_Out";
						mission.order_type = "C";
						break;
					case "3":  //盘点
						mission.task_type = "ST_Check";
						mission.order_type = "P";
						break;
					case "4":  //库内移动
						mission.task_type = "ST_Move";
						mission.order_type = "Y";
						break;
					default:
						mission.task_type = "null";
						mission.order_type = "null";
						break;
				}
				mission.tunnel_no = request.roadWay; //入库巷道号
				mission.tray_type = request.cntrType;
				mission.MissionState = "Create";
				mission.CreateTime = DateTime.Now;
				mission.ope_time = DateTime.Now;
				//agv放货完成之后到读码器交互点
				mission.InteStationNo = convertedFrom == "101010" ? "101011" :
					convertedFrom == "101009" ? "101007" :
					convertedFrom;
				mission.SyncFlag = "U"; //未同步
				//判断任务号是否已存在
				IMainMissionRepository mainMissionRepository = new MainMissionRepository();
				MainMissionEntity mainMission = mainMissionRepository.FindEntity(m => m.task_no == request.taskNo);
				if (mainMission != null)
				{
					//任务号已存在
					return BuildResponse(-1, "任务号已存在，请检查任务号是否正确！", null);
				}
				if (mission != null)
				{
					//写入数据库
					AutoScanApp autoScanApp = new AutoScanApp();
					bool mainResult = autoScanApp.AddMainMissionList(mission, out string mainMsg);
					if (!mainResult)
					{
						//任务写入数据库失败
						return BuildResponse(-1, "数据库任务写入失败" + mainMsg, null);
					}
				}
				
				return BuildResponse(0, "success", null);
			}
			catch (Exception ex)
			{
				return BuildResponse(-1, "捕获异常"+ex.Message, null);
			}
		}

		/// <summary>
		/// IC02.作业任务取消
		/// </summary>
		/// <param name="requestJson"></param>
		/// <returns></returns>
		public static string CancelTask(string requestJson)
		{
			//todo 后续加入agv 需要考虑任务是否发送给agv
			try
			{
				var request = JsonConvert.DeserializeObject<ToWmsCancelOrderRequest>(requestJson);
				if (request == null)
					return BuildResponse(-1, "收到的json格式不正确", null);

				if (string.IsNullOrEmpty(request.taskNo))
					return BuildResponse(-1, "taskNo不能为空", null);

				var mainMission = new MainMissionRepository().FindEntity(m => m.task_no == request.taskNo);
				if (mainMission == null)
					return BuildResponse(-1, "任务号不存在，请检查任务号是否正确！", null);

				if (mainMission.MissionState ==  "Cancel" || mainMission.MissionState == "Error")
					return BuildResponse(-1, "任务已取消或异常，不能再次取消", null);

				// 查询堆垛机任务
				var stackerTask = new StackerTaskRepository().FindEntity(m => m.TaskNo == request.taskNo);
				AutoScanApp autoScan = new AutoScanApp();

				// 更新主任务状态
				mainMission.MissionState = "Cancel";
				mainMission.ope_time = DateTime.Now;
				mainMission.LastUpdatedTime = DateTime.Now;
				mainMission.MissionEndTime = DateTime.Now;
				mainMission.reverse_6 = "WMS取消任务"; // 取消任务标记

				if (stackerTask != null)
				{
					if (stackerTask.TaskState != "Create" || stackerTask.AbnormalFlag == "1")
						return BuildResponse(-1, "任务正在堆垛机执行中，不能取消", null);

					stackerTask.TaskState = "Cancel";
					stackerTask.LastUpdatedTime = DateTime.Now;
					stackerTask.reverse_6 = "WMS取消任务"; // 取消任务标记

					if (!autoScan.UpdateStackerAndMainTask(stackerTask, mainMission, out string msg))
						return BuildResponse(-1, $"堆垛机任务写入失败: {msg}", null);

					return BuildResponse(0, "success", null);
				}

				// 如果没有堆垛机任务，只更新主任务
				if (!autoScan.UpdateMainMissionTask(mainMission, out string mainMsg))
					return BuildResponse(-1, $"任务写入失败: {mainMsg}", null);

				return BuildResponse(0, "success", null);
			}
			catch (Exception ex)
			{
				return BuildResponse(-1, $"取消任务异常: {ex.Message}", null);
			}
		}


		/// <summary>
		/// IC03.设备状态获取
		/// </summary>
		/// <param name="requestJson"></param>
		/// <returns></returns>
		public static string GetDvcState(string requestJson)
		{
			//string respJson = string.Empty;
			try
			{
				var request = JsonConvert.DeserializeObject<ToWmsGetStateRequest>(requestJson);
				if (request == null)
				{
					return DvcStateResponse(-1, "收到的json格式不正确", null);
				}
				else
				{
					// 1. 设备号不能为空
					if (request.deviceNo == null || request.deviceNo.Count == 0)
					{
						return DvcStateResponse(-1, "请求deviceNo的数组不能为空", null);
					}

					var deviceDataList = new List<DeviceData>();
					//如果是堆垛机就看是否报警在联机自动的情况
					//如果是入库口的工位，就看是否可入，是否报警
					//根据设备号查询设备状态
					foreach (var deviceNo in request.deviceNo.Where(d => !string.IsNullOrEmpty(d)))
					{
						int deviceStatus = 1; //默认1为不可用

						if (deviceNo.StartsWith("TC"))
						{
							string modeValue = Conn.YBRedis.GetValue($"{deviceNo}.dev_pattern");
							string faultValue = Conn.YBRedis.GetValue($"{deviceNo}.dev_error");

							if (modeValue == "1" && faultValue == "0")
							{
								deviceStatus = 0;
							}
						}
						else
						{
							string wcsDeviceNo = StationConvertHelper.ConvertWmsToWcs(deviceNo);

							if (wcsDeviceNo == null)
							{
								return DvcStateResponse(-1, "设备编号未在双方系统维护范围内", null);
							}
							string canIn = Conn.YBRedis.GetValue($"CV01.PLC_CANIN_{wcsDeviceNo}");
							if (canIn == "1")
							{
								deviceStatus = 0;
							}
						}

						deviceDataList.Add(new DeviceData { deviceNo = deviceNo, status = deviceStatus });
					}

					return DvcStateResponse(0, "success", deviceDataList);
				}
			}
			catch (Exception ex)
			{
				return DvcStateResponse(-1, ex.Message, null);
			}
		}

		/// <summary>
		/// IC04.任务优先级调整
		/// </summary>
		/// <param name="requestJson"></param>
		/// <returns></returns>
		public static string ModifyPriority(string requestJson)
		{
			//string respJson = string.Empty;
			try
			{
				var request = JsonConvert.DeserializeObject<ToWmsOrderPriorityRequest>(requestJson);
				if (request == null)
				{
					return BuildResponse(-1, "收到的json格式不正确", null);
				}
				else
				{
					// 1. 任务号不能为空
					if (string.IsNullOrEmpty(request.taskNo))
					{
						return BuildResponse(-1, "taskNo不能为空", null);
					}
					// 2. 优先级不能为空
					if (request.priority <= 0)
					{
						return BuildResponse(-1, "priority不能为负数", null);
					}
					//1.查主任务是否为出库并且确认堆垛机任务是否已经执行了
					//2.判断出库的优先级是否有移库任务
					//3.准备将任务号、优先级等信息存入数据库
					IMainMissionRepository mainMissionRepository = new MainMissionRepository();
					//任务号已存在
					var mission = mainMissionRepository.FindEntity(m => m.task_no == request.taskNo);
					if (mission != null)
					{
						if(mission.task_type == "ST_In")
						{
							return BuildResponse(-1, "入库任务暂不提供优先级修改", null);
						}
						if(mission.MissionState == "Finish" || mission.MissionState == "Cancel")
						{
							return BuildResponse(-1, "任务已完成或已取消，无法修改", null);
						}
						IStackerTaskRepository stackerTaskRepository = new StackerTaskRepository();
						StackerTaskEntity stackerTask = stackerTaskRepository.FindEntity(m => m.TaskNo == mission.task_no && m.TaskState == "Create");
						if (stackerTask != null)
						{
							//如果当前的堆垛机任务是奇数排，就+1排 同列同层是否有移库任务  任务是偶数排 就-1排 同列同层是否有移库任务
							//如果有移库任务也是创建的,把移库的优先级也更新
							
							// 获取当前任务的位置信息
							int currentX = stackerTask.FromX ?? 0; // 排
							int currentY = stackerTask.FromY ?? 0; // 列
							int currentZ = stackerTask.FromZ ?? 0; // 层
							
							int adjacentX;
							if (currentX % 2 == 1) // 奇数排
							{
								adjacentX = currentX + 1; // +1排
							}
							else // 偶数排
							{
								adjacentX = currentX - 1; // -1排
							}
							
							// 查找相邻排同列同层的移库任务（状态为Create）
							var adjacentTask = stackerTaskRepository.FindEntity(m =>
							                                                    m.FromX == adjacentX &&
							                                                    m.FromY == currentY &&
							                                                    m.FromZ == currentZ &&
							                                                    m.TaskState == "Create" &&
							                                                    m.TaskType == "ST_Move");
							
							bool mainbl ;
							AutoScanApp autosan = new AutoScanApp();
							string mainessmage ;

							if(adjacentTask != null)
							{
								adjacentTask.PriorityLevel = request.priority;
								adjacentTask.LastUpdatedTime = DateTime.Now;
							}
							
							mission.task_priority = request.priority;
							mission.LastUpdatedTime = DateTime.Now;
							stackerTask.PriorityLevel = request.priority;
							stackerTask.LastUpdatedTime = DateTime.Now;
							
							//判断任务写入数据库是否成功
							if(adjacentTask != null)
							{
								mainbl = autosan.UpdateStackerTwoAndMainTask(stackerTask,adjacentTask,mission, out mainessmage);
							}
							else
							{
								mainbl = autosan.UpdateStackerAndMainTask(stackerTask, mission, out mainessmage);
							}
							if (mainbl)
							{
								return BuildResponse(0, "success", null);
							}
							else
							{
								return BuildResponse(-1, "堆垛机或主任务写入失败" + mainessmage, null);
							}
						}
						else
						{
							mission.task_priority = request.priority;
							mission.LastUpdatedTime = DateTime.Now;
							//判断任务写入数据库是否成功
							AutoScanApp autosan = new AutoScanApp();
							bool mainbl = autosan.UpdateMainMissionTask(mission, out string mainessmage);
							if (mainbl)
							{
								return BuildResponse(0, "success", null);
							}
							else
							{
								return BuildResponse(-1, "主任务写入失败" + mainessmage, null);
							}
						}
						
					}
					else
					{
						return BuildResponse(-1, "请检查任务号[" + request.taskNo + "]是否正确下发WCS任务！", null);
					}
				}
			}
			catch (Exception ex)
			{
				return BuildResponse(-1, ex.Message, null);
			}
		}
		
		/// <summary>
		/// IC05.是否允许进入
		/// </summary>
		/// <param name="requestJson"></param>
		/// <returns></returns>
		public static string IsAllow(string requestJson)
		{
			try
			{
				var request = JsonConvert.DeserializeObject<ToWmsIsAllowRequest>(requestJson);
				if (request == null)
				{
					return IsAllowResponse(-1, "收到的json格式不正确");
				}

				// 1. 请求编号不能为空
				if (string.IsNullOrWhiteSpace(request.requestPk))
				{
					return IsAllowResponse(-1, "requestPk不能为空");
				}

				// 2. 请求类型不能为空且必须在 1~4 范围内
				if (request.trkType < 1 || request.trkType > 4)
				{
					return IsAllowResponse(-1, "trkType必须在1~4之间");
				}

				// 3. 请求站台不能为空
				if (string.IsNullOrWhiteSpace(request.stnNo))
				{
					return IsAllowResponse(-1, "stnNo不能为空");
				}

				// ==================
				// 按 trkType 分类逻辑
				// ==================
				string stn = StationConvertHelper.ConvertWmsToWcs(request.stnNo);//后续通过StationConvertHelper
				string queue = "CV01Queue";

				switch (request.trkType)
				{
					case 1: // 请求取货
						{
							string canOut = Conn.YBRedis.GetValue($"CV01.PLC_CANOUT_{stn}");
							return canOut == "1"
								? IsAllowResponse(0, "允许进入")
								: IsAllowResponse(1, "输送线未给允许取货信号");
						}

					case 2: // 请求放货
						{
							string canIn = Conn.YBRedis.GetValue($"CV01.PLC_CANIN_{stn}");
							return canIn == "1"
								? IsAllowResponse(0, "允许进入")
								: IsAllowResponse(1, "输送线未给允许放货信号");
						}

					case 3: // 取货完成
						{
							bool res = Conn.YBRedis.SetValue($"CV01.WCS_OUTFINISHSENT_{stn}", "1", queue);
							return res
								? IsAllowResponse(0, "success")
								: IsAllowResponse(1, "站台取货完成redis写入失败");
						}

					case 4: // 放货完成
						{
							bool res = Conn.YBRedis.SetValue($"CV01.WCS_INFINISHSENT_{stn}", "1", queue);
							return res
								? IsAllowResponse(0, "success")
								: IsAllowResponse(1, "站台放货完成redis写入失败");
						}

					default:
						return IsAllowResponse(1, "未知的trkType类型");
				}
			}
			catch (Exception ex)
			{
				// 捕获异常并返回更详细的信息（保留异常消息，避免抛出到外部）
				return IsAllowResponse(1, $"异常: {ex.Message}");
			}
		}

	}

}